package com.spn.blog.login.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.spn.blog.common.dao.pojo.ChatHistory;
import com.spn.blog.common.dao.pojo.LoginUser;
import com.spn.blog.common.dao.pojo.SysUser;
import com.spn.blog.common.dao.pojo.SysUserTpusers;
import com.spn.blog.common.utils.JWTUtils;
import com.spn.blog.common.utils.QiniuUtils;
import com.spn.blog.common.utils.RedisCacheUtil;
import com.spn.blog.login.mapper.ChatHistoryMapper;
import com.spn.blog.login.mapper.MenuMapper;
import com.spn.blog.common.vo.FriendVO;
import com.spn.blog.common.vo.ChatHistoryVo;
import com.spn.blog.login.utils.QueryHelper;
import org.apache.commons.lang3.StringUtils;
import com.spn.blog.common.vo.ErrorCode;
import com.spn.blog.common.vo.LoginUserVo;
import com.spn.blog.common.vo.Result;
import com.spn.blog.common.vo.UserVo;
import com.spn.blog.login.mapper.SysUserMapper;
import com.spn.blog.login.mapper.SysUserTpusersMapper;
import com.spn.blog.service.login.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@DubboService
@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserTpusersMapper sysUserTPUsersMapper;
    @Autowired
    private RedisCacheUtil redisCacheUtil;
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private ChatHistoryMapper chatHistoryMapper;


    @Override
    public SysUser findUserById(String id) {
        SysUser sysUser = sysUserMapper.selectById(id);
        //防止空指针的出现
        if (sysUser == null) {
            sysUser = new SysUser();
            sysUser.setNickname("用户不存在");
        }
        return sysUser;
    }

    @Override
    public SysUser findUser(String account, String password) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        //查询数据库【SysUser::getAccount】字段是否有account这个值
        queryWrapper.eq(SysUser::getAccount,account);
        queryWrapper.eq(SysUser::getPassword, password);
        queryWrapper.select(
                SysUser::getAccount,
                SysUser::getId,
                SysUser::getAvatar,
                SysUser::getNickname,
                SysUser::getUserType
        );
        //加这条语句防止SQL一直查询下去，提升查询效率
        queryWrapper.last("limit 1");
        return sysUserMapper.selectOne(queryWrapper);
    }


    @Override
    public Result findUserByToken(String token) {
        /**
         * 1. token 合法性校验
         *      是否为空，解析是否成功，redis是否存在此token
         * 2. 如果校验失败 返回错误
         * 3. 如果成功，返回对应结果 LoginUserVo
         */
        SysUser sysUser = checkToken(token);
        if (sysUser == null) {
            Result.fail(ErrorCode.TOKEN_ERROR.getCode(), ErrorCode.TOKEN_ERROR.getMsg());
        }
        LoginUserVo loginUserVo = new LoginUserVo();
        loginUserVo.setId(String.valueOf(sysUser.getId()));
        loginUserVo.setNickname(sysUser.getNickname());
        loginUserVo.setAccount(sysUser.getAccount());
        loginUserVo.setAvatar(sysUser.getAvatar());
        loginUserVo.setUserType(sysUser.getUserType());
        String loginIp = sysUser.getLoginIp();
        String belongingJSON = QueryHelper.queryIP(loginIp);
        /*
        {
            "ret":"ok",
            "ip":"1.205.148.220",
            "data":["中国","贵州","遵义","桐梓","电信","563200","0851"]
        }
         */
        String belonging = "";
        if (!StringUtils.isBlank(belongingJSON)){ //TODO findUserByToken(SysUserServiceImpl.java:109) null
            Map map = JSONObject.parseObject(belongingJSON, Map.class);
            List<String> data = (List<String>)map.get("data");
            for (int i = 0; i < 4; i++) {
                belonging = belonging + " " + data.get(i);
            }
        }

        loginUserVo.setArea(belonging);
        return Result.success(loginUserVo);
    }

    public SysUser checkToken(String token) {
        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isBlank(token)) {
            //无token
            return null;
        }
        Map<String, Object> stringObjectMap = JWTUtils.checkToken(token);
        if (stringObjectMap == null) {
            //有token，但是token不匹配
            return null;
        }
        //从redis里面取sysUser，效率比数据库取要高
        Map<String, Object> map = JWTUtils.checkToken(token);
        String userId = (String)map.get("userId");
        JSONObject jsonObject = redisCacheUtil.getCacheObject("TOKEN:" + userId);
        LoginUser loginUser = jsonObject.toJavaObject(LoginUser.class);
        if (Objects.isNull(loginUser)) {
            //token匹配，但是redis不存在此token
            return null;
        }
        //token校验通过，返回该sysUser信息
        SysUser sysUser = loginUser.getSysUser();
        return sysUser;
    }

    @Override
    public SysUser findUserByAccount(String account) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getAccount, account);
        queryWrapper.last("limit 1");
        return sysUserMapper.selectOne(queryWrapper);
    }

    @Override
    public UserVo findUserVoById(String authorId) {
        SysUser sysUser = sysUserMapper.selectById(authorId);
        //防止空指针的出现
        if (sysUser == null) {
            //若用户不存在，表示用户已经注销了账号
            sysUser = new SysUser();
            sysUser.setId("1");
            sysUser.setAvatar("/static/img/logo.b3a48c0.png");
            sysUser.setNickname("该用户已注销");
        }
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(sysUser, userVo);
        userVo.setId(String.valueOf(sysUser.getId()));
        return userVo;
    }

    @Override
    public Result findUserDetailByToken(String token) {
        /**
         * 1. token 合法性校验
         *      是否为空，解析是否成功，redis是否存在此token
         * 2. 如果校验失败 返回错误
         * 3. 如果成功，返回对应结果 LoginUserVo
         */
        SysUser sysUser = checkToken(token);
        if (sysUser == null) {
            Result.fail(ErrorCode.TOKEN_ERROR.getCode(), ErrorCode.TOKEN_ERROR.getMsg());
        }
        sysUser = sysUserMapper.selectById(sysUser.getId());
        log.debug(sysUser.toString());
        return Result.success(sysUser);
    }



    @Override
    public SysUser findUserBytpUserId(String id) {
        /**
         * 这个id是tpid，从后台查询这个id的user
         */
        LambdaQueryWrapper<SysUserTpusers> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUserTpusers::getTpusersId, id);
        SysUserTpusers sysUserTPUsers = sysUserTPUsersMapper.selectOne(queryWrapper);
        if (sysUserTPUsers != null) {
            SysUser user = this.findUserById(sysUserTPUsers.getSysUserId());
            return user;
        }
        return null;
    }

    @Override
    public Result sendSms(String phone) {

        return null;
    }


    @Transactional
    @Override
    public Result upload(Map<String, Object> imgMap, String userId) {

        // 从redis获取当前用户
        JSONObject jsonObject = redisCacheUtil.getCacheObject("TOKEN:" + userId);
        LoginUser loginUser = jsonObject.toJavaObject(LoginUser.class);

        // 1. 把图片上传到七牛云。
        // MultipartFile Spirng专门接受文件的类型，@RequestParam注解用于接受文件
        // 原始文件名称，例如 aa.png,我们不要原始名字，我们要UUID加工过的名字。
        String originalFilename = (String)imgMap.get("originalFilename");
        // UUID唯一名字
        String fileName = UUID.randomUUID().toString()
                + "."
                + StringUtils.substringAfterLast(originalFilename, ".");
        // 我们图片不使用应用服务器，可能会造成网络拥堵。使用一个图片服务器
        // 我们这里使用七牛云提供的免费服务器，按量付费，速度快
        byte[] bytes = (byte[]) imgMap.get("bytes");
        boolean upload = QiniuUtils.upload(bytes, fileName);
        if (upload) {
            // 2. 把图片地址存储到用户表中
            SysUser sysUser = loginUser.getSysUser();
            sysUser.setAvatar(QiniuUtils.url+ fileName);
            sysUserMapper.updateById(sysUser);
            // 3. 更新用户的redis数据
            loginUser.setSysUser(sysUser);
            redisCacheUtil.setCacheObject("TOKEN:" + sysUser.getId(), loginUser);
            return Result.success(QiniuUtils.url + fileName);
        }
        return Result.fail(20001, "上传失败");
    }

    @Override
    public SysUser findUserByEmail(String email) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getEmail, email);
        return sysUserMapper.selectOne(queryWrapper);
    }

    @Override
    public Integer updateById(SysUser sysUser) {
        return sysUserMapper.updateById(sysUser);
    }

    @Override
    public Integer save(SysUser sysUser) {
        return sysUserMapper.insert(sysUser);
    }

    @Override
    public SysUser getOne(String password, String email) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<SysUser> eq = queryWrapper.eq(SysUser::getPassword, password).eq(SysUser::getEmail, email);
        return sysUserMapper.selectOne(eq);
    }

    @Override
    public Integer initAccessDenied(String id) {
        Integer role1 = sysUserMapper.initAccessDeniedRole(id,"1");// 普通用户权限

        Integer role2 = sysUserMapper.initAccessDeniedRole(id,"2");// 游客权限

        return role1 + role2;
    }

    @Override
    public List<String> selectPermsByUserId(String id) {
        return menuMapper.selectPermsByUserId(id);
    }


    @Override
    public Result getAllFriends(String token) {
        //TODO:wb接口还没完成
        Map<String, Object> map = JWTUtils.checkToken(token);
        String userId = (String)map.get(JWTUtils.userKey);
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ne(SysUser::getId, userId);
        List<SysUser> sysUsers = sysUserMapper.selectList(queryWrapper);
        List<FriendVO> res = new ArrayList<>();
        for (SysUser sysUser : sysUsers) {
            FriendVO friendVO = new FriendVO();
            BeanUtils.copyProperties(sysUser, friendVO);
            friendVO.setFirstmsg("亲，欢迎您的关注哦！");
            res.add(friendVO);
        }
        return Result.success(res);
    }

    @Override
    public Result getHistoryMsg(String token, String to) {
        Map<String, Object> map = JWTUtils.checkToken(token);
        String curId = (String)map.get(JWTUtils.userKey);
        List<ChatHistoryVo> res = new ArrayList<>();
        LambdaQueryWrapper<ChatHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatHistory::getUserId, curId).eq(ChatHistory::getToId, to)
                .or()
                .eq(ChatHistory::getToId, curId).eq(ChatHistory::getUserId, to)
                .orderBy(true, true, ChatHistory::getDate);
        List<ChatHistory> chatHistories = chatHistoryMapper.selectList(queryWrapper);
        for (ChatHistory chatHistory : chatHistories) {
            ChatHistoryVo chatHistoryVo = new ChatHistoryVo();
            BeanUtils.copyProperties(chatHistory, chatHistoryVo);
            SysUser sysUser = sysUserMapper.selectById(chatHistory.getUserId());
            if(chatHistory.getUserId().equals(to)){
                // to
                chatHistoryVo.setMine(false);
            }else{
                // from
                chatHistoryVo.setMine(true);
            }
            HashMap<String, String> objectObjectHashMap = new HashMap<>();
            objectObjectHashMap.put("text", chatHistory.getText());
            chatHistoryVo.setText(objectObjectHashMap);
            chatHistoryVo.setImg(sysUser.getAvatar());
            chatHistoryVo.setName(sysUser.getNickname());
            res.add(chatHistoryVo);
        }

        return Result.success(res);
    }

    @Override
    public boolean insertChatHistory(ChatHistory chatHistory) {
        int insert = chatHistoryMapper.insert(chatHistory);
        if (insert != 0) {
            return true;
        } else {
            return false;
        }
    }
}
